package com.floreantpos.ui.views;

import java.awt.LayoutManager;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

import com.floreantpos.POSConstants;
import com.floreantpos.main.Application;
import com.floreantpos.model.Guest;
import com.floreantpos.model.PosTransaction;
import com.floreantpos.model.Ticket;
import com.floreantpos.model.dao.GuestDAO;
import com.floreantpos.services.PosTransactionService;
import com.floreantpos.swing.MessageDialog;
import com.floreantpos.ui.dialog.POSMessageDialog;
import com.floreantpos.ui.dialog.PaymentTypeSelectionDialog;
import com.floreantpos.ui.dialog.TransactionCompletionDialog;
import com.floreantpos.ui.views.order.RootView;
import java.text.NumberFormat;
import java.util.Locale;

public abstract class PaymentView extends JPanel {

  protected SettleTicketView settleTicketView;

  NumberFormat numberFormat = NumberFormat.getInstance(new Locale("pt", "BR"));
  
  public PaymentView(LayoutManager layout, boolean isDoubleBuffered) {
    super(layout, isDoubleBuffered);
  }

  public PaymentView(LayoutManager layout) {
    super(layout);
  }

  public PaymentView(boolean isDoubleBuffered) {
    super(isDoubleBuffered);
  }

  public PaymentView() {
    super();
  }

  public SettleTicketView getSettleTicketView() {
    return settleTicketView;
  }

  public void setSettleTicketView(SettleTicketView settleTicketView) {
    this.settleTicketView = settleTicketView;
  }

  protected double getTotalAmount() {
    List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();
    if (ticketsToSettle == null) {
      return 0;
    }

    double total = 0;
    for (Ticket ticket : ticketsToSettle) {
      total += ticket.getTotalAmount();
    }
    return total;
  }

  protected double getPaidAmount() {
    List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();
    if (ticketsToSettle == null) {
      return 0;
    }

    double total = 0;
    for (Ticket ticket : ticketsToSettle) {
      total += ticket.getPaidAmount();
    }
    return total;
  }

  protected double getDueAmount() {
    List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();
    if (ticketsToSettle == null) {
      return 0;
    }

    double total = 0;
    for (Ticket ticket : ticketsToSettle) {
      total += ticket.getDueAmount();
    }
    return total;
  }

  protected double getTotalGratuity() {
    List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();
    if (ticketsToSettle == null) {
      return 0;
    }

    double total = 0;
    for (Ticket ticket : ticketsToSettle) {
      total += ticket.getGratuityAmount();
    }
    return total;
  }

  public void changePaymentMethod(String taxId) {
    PaymentTypeSelectionDialog dialog = new PaymentTypeSelectionDialog(taxId);
    dialog.setSize(250, 400);
    dialog.open();
    if (!dialog.isCanceled()) {
      SettleTicketView view = SettleTicketView.getInstance();
      view.setPaymentView(dialog.getSelectedPaymentView());

      view.setTicketsToSettle(settleTicketView.getTicketsToSettle());

      RootView.getInstance().showView(SettleTicketView.VIEW_NAME);
    }
  }

  public void changePaymentMethod(Boolean giftCertEnabled, int registeredGuest, String taxId) {
    PaymentTypeSelectionDialog dialog = new PaymentTypeSelectionDialog(giftCertEnabled, registeredGuest, taxId);
    dialog.setSize(250, 400);
    dialog.open();
    if (!dialog.isCanceled()) {
      SettleTicketView view = SettleTicketView.getInstance();
      view.setPaymentView(dialog.getSelectedPaymentView());

      view.setTicketsToSettle(settleTicketView.getTicketsToSettle());

      RootView.getInstance().showView(SettleTicketView.VIEW_NAME);
    }
  }

  public Boolean ticketNotesExist() {
    List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();
    int ticketsWithoutNotes = 0;

    for (Ticket ticket : ticketsToSettle) {
      if (ticket.getNotes() == null) {
        ticketsWithoutNotes = ticketsWithoutNotes + 1;
      }
    }

    if (ticketsWithoutNotes > 0) {
      return false;
    }

    return true;
  }
  
  public Boolean isTicketDiscountOk() {
    List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();

    for (Ticket ticket : ticketsToSettle) { 
      if (ticket.getDiscountAmount() >= ticket.getSubtotalAmount()) {
        return false;
      }
    }
    
    return true;
  } 
    
  public void updateTicketGuest(int GuestID) {
    List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();
    for (Ticket ticket : ticketsToSettle) {
      if (ticket.getRegisteredGuest() == null) {
        GuestDAO dao = GuestDAO.getInstance();
        Guest registeredGuest = dao.get(GuestID);

        if (registeredGuest != null) {

          String guestName = registeredGuest.getName();

          String notes = registeredGuest.getTelephone() + "|" + registeredGuest.getAddressLine1();

          if (!registeredGuest.getAddressLine2().isEmpty()) {
            notes = notes + " - " + registeredGuest.getAddressLine2();
          }

          if (!registeredGuest.getAddressLine3().isEmpty()) {
            notes = notes + " - " + registeredGuest.getAddressLine3();
          }

          String ticketNotes = ticket.getNotes();

          if (ticketNotes == null) {
            notes = notes + "|";
          } else {
            notes = notes + "|" + ticket.getNotes();
          }

          ticket.setRegisteredGuest(GuestID);
          ticket.setGuest(guestName);
          ticket.setNotes(notes);
        }
      }
    }
  }

  public void settleTickets(double tenderedAmount, double gratuityAmount, PosTransaction posTransaction, String cardType, String cardAuthorizationCode, String taxId) {
    try {

      double totalAmount = numberFormat.parse(Application.formatNumber(getTotalAmount())).doubleValue();
      double dueAmountBeforePaid = numberFormat.parse(Application.formatNumber(getDueAmount())).doubleValue();
      
      Boolean paymentTicket = false;

      List<Ticket> ticketsToSettle = settleTicketView.getTicketsToSettle();

      if (ticketsToSettle.size() > 1 && tenderedAmount < dueAmountBeforePaid) {
        MessageDialog.showError(com.floreantpos.POSConstants.YOU_CANNOT_PARTIALLY_PAY_MULTIPLE_TICKETS_);
        return;
      }

      if (ticketsToSettle.size() == 1) {
        Ticket ticket = ticketsToSettle.get(0);
        if (ticket.isPaymentTicket() && tenderedAmount != dueAmountBeforePaid) {
          MessageDialog.showError(com.floreantpos.POSConstants.PAYMENT_ERROR);
          return;
        }
        if (ticket.isPaymentTicket()) {
          paymentTicket = true;
        }
      }

      PosTransactionService service = PosTransactionService.getInstance();
      service.settleTickets(ticketsToSettle, tenderedAmount, gratuityAmount, posTransaction, cardType, cardAuthorizationCode, taxId);
      
      double paidAmount = numberFormat.parse(Application.formatNumber(getPaidAmount())).doubleValue();
      double dueAmount = numberFormat.parse(Application.formatNumber(getDueAmount())).doubleValue();

      TransactionCompletionDialog dialog = TransactionCompletionDialog.getInstance();
      dialog.setTickets(ticketsToSettle);
      dialog.setTenderedAmount(tenderedAmount);
      dialog.setTotalAmount(totalAmount);
      dialog.setPaidAmount(paidAmount);
      dialog.setDueAmount(dueAmount);
      dialog.setDueAmountBeforePaid(dueAmountBeforePaid);
      dialog.setGratuityAmount(gratuityAmount);
      dialog.setPaymentTicket(paymentTicket);
      dialog.updateView();
      dialog.pack();
      dialog.open();

      if (dueAmount > 0.0) {
        int option = JOptionPane.YES_OPTION;
        if (Application.isDemo()) {
          option = JOptionPane.showConfirmDialog(Application.getPosWindow(), com.floreantpos.POSConstants.CONFIRM_PARTIAL_PAYMENT, com.floreantpos.POSConstants.MDS_POS, JOptionPane.YES_NO_OPTION);  
        } else {
          JOptionPane.showMessageDialog(null, "Foi registrado um pagamento parcial, por favor registre mais um pagamento.", com.floreantpos.POSConstants.MDS_POS, JOptionPane.INFORMATION_MESSAGE, null);
        }
        if (option != JOptionPane.YES_OPTION) {
          RootView.getInstance().showView(SwitchboardView.VIEW_NAME);
          return;
        }
        
        PaymentTypeSelectionDialog paymentTypeSelectionDialog = new PaymentTypeSelectionDialog(false, taxId);
        
        paymentTypeSelectionDialog.setSize(250, 400);
        paymentTypeSelectionDialog.open();

        if (!paymentTypeSelectionDialog.isCanceled()) {
          settleTicketView.setPaymentView(paymentTypeSelectionDialog.getSelectedPaymentView());
          settleTicketView.setTicketsToSettle(ticketsToSettle);
        }
      } else {
        RootView.getInstance().showView(SwitchboardView.VIEW_NAME);
      }
    } catch (Exception e) {
      POSMessageDialog.showError(this, POSConstants.ERROR_MESSAGE, e);
    }
  }

  public abstract void updateView();
}
